package cn.funeralobjects.upms.service.impl;

import cn.funeralobjects.common.jpa.service.*;
import cn.funeralobjects.common.repository.*;
import cn.funeralobjects.common.service.annotataion.CommonService;
import cn.funeralobjects.common.service.exception.DataConflictException;
import cn.funeralobjects.upms.entity.EUser;
import cn.funeralobjects.upms.entity.EUserAuthSerial;
import cn.funeralobjects.upms.model.User;
import cn.funeralobjects.upms.repository.UserAuthSerialRepository;
import cn.funeralobjects.upms.repository.UserRepository;
import cn.funeralobjects.upms.service.UserService;
import cn.funeralobjects.util.Assert;
import cn.funeralobjects.util.NumberUtils;
import cn.funeralobjects.util.annotation.ArgHasLength;
import cn.funeralobjects.util.annotation.ArgNotZero;
import cn.funeralobjects.util.annotation.AssertArg;
import org.springframework.data.repository.CrudRepository;

import javax.annotation.Resource;
import java.util.UUID;

/**
 * UserService的实现类
 *
 * @author FuneralObjects
 * Create date: 2020/4/20 9:30 AM
 */
@CommonService
public class UserServiceImpl implements UserService,
        JpaModifyService<User, EUser, Integer>,
        JpaEntityService<EUser, Integer>,
        JpaCodeService<EUser, Integer>,
        JpaEnableService<EUser, Integer>,
        JpaDelSaltService<EUser, Integer>,
        JpaCommitService<Integer> {

    @Resource
    private UserRepository userRepository;

    @Resource
    private UserAuthSerialRepository userAuthSerialRepository;

    @AssertArg
    @Override
    public String getAuthUserSerial(@ArgNotZero Integer userId) {
        return userAuthSerialRepository.findById(userId).map(EUserAuthSerial::getSerial).orElse(null);
    }

    @Override
    public void refreshAuthUserSerial(Integer userId) {
        mustExistsById(userId);
        userAuthSerialRepository.save(new EUserAuthSerial().setUserId(userId).setSerial(generatorSerial()));
    }

    private Integer getExistsDelSalt() {
        return (Integer) userRepository.getDefaultExistsDelSalt();
    }

    private static String generatorSerial() {
        return UUID.randomUUID().toString();
    }

    @Override
    public CodeRepository<EUser, Integer> codeRepository() {
        return userRepository;
    }

    @AssertArg
    @Override
    public boolean existsByCode(@ArgHasLength String code) {
        return userRepository.existsAllByCodeAndDelSalt(code, getExistsDelSalt());
    }

    @AssertArg
    @Override
    public void checkConflict(@AssertArg User user) throws DataConflictException {
        this.mustNotConflictByCode(user.getCode());
    }

    @Override
    public EUser toEntity(User user) {
        if (user == null) {
            return null;
        }
        EUser entity = new EUser();
        entity.setCode(user.getCode());
        return entity;
    }

    @AssertArg
    @Override
    public void checkConflict(@AssertArg User user, @ArgNotZero Integer withoutId) throws DataConflictException {
        this.mustNotConflictByCode(user.getCode(), withoutId);
    }

    @Override
    public void copyToEntity(User sourceModify, EUser targetEntity) {
        targetEntity.setCode(sourceModify.getCode());
    }

    @Override
    public void validateModify(User user) {
        Assert.argAssert(user, "user");
    }

    @Override
    public CommitRepository<Integer> commitRepository() {
        return userRepository;
    }

    @Override
    public DelSaltRepository<EUser, Integer> delSaltRepository() {
        return userRepository;
    }

    @Override
    public EnableRepository<EUser, Integer> enableRepository() {
        return userRepository;
    }

    @Override
    public EntityRepository<EUser, Integer> entityRepository() {
        return userRepository;
    }

    @Override
    public CrudRepository<EUser, Integer> modifyRepository() {
        return userRepository;
    }

    @Override
    public boolean isValid(Integer id) {
        return NumberUtils.notZero(id);
    }
}
